package com.cyh;

import org.apache.http.HttpEntity;
import org.apache.http.HttpEntityEnclosingRequest;
import org.apache.http.HttpRequest;
import org.apache.http.NoHttpResponseException;
import org.apache.http.client.HttpRequestRetryHandler;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpUriRequest;
import org.apache.http.client.protocol.HttpClientContext;
import org.apache.http.conn.ConnectTimeoutException;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
import org.apache.http.util.EntityUtils;

import javax.net.ssl.SSLException;
import javax.net.ssl.SSLHandshakeException;
import java.io.InterruptedIOException;
import java.net.UnknownHostException;
import java.nio.charset.StandardCharsets;
import java.util.concurrent.TimeUnit;

/**
 * @author CYH
 * @date 2019-09-20 HttpClient及配置（重试配置）
 */
public class MyHttpClient {

    private static CloseableHttpClient httpClient;

    static {
        PoolingHttpClientConnectionManager cm = new PoolingHttpClientConnectionManager(1, TimeUnit.MINUTES);
        cm.setMaxTotal(8192);
        cm.setDefaultMaxPerRoute(1024);

        HttpRequestRetryHandler retryHandler = (e, executionCount, context) -> {
            if (executionCount >= 3) {
                return false;
            }
            if (e instanceof NoHttpResponseException) {
                return true;
            }
            if (e instanceof SSLHandshakeException) {
                return false;
            }
            if (e instanceof InterruptedIOException) {
                System.err.println("InterruptedIOException==> " + e);
                /**
                 * SocketTimeoutException继承了这个类
                 * 所以自主考虑如果出现了此异常，要不要重试
                 */
                return true;
            }
            if (e instanceof UnknownHostException) {
                return false;
            }
            if (e instanceof ConnectTimeoutException) {
                return false;
            }
            if (e instanceof SSLException) {
                return false;
            }

            HttpClientContext clientContext = HttpClientContext.adapt(context);
            HttpRequest request = clientContext.getRequest();

            // 如果请求是幂等的，就再次尝试
            if (!(request instanceof HttpEntityEnclosingRequest)) {
                return true;
            }
            return false;
        };

        RequestConfig requestConfig = RequestConfig.custom()
                .setConnectionRequestTimeout(1000)
                .setConnectTimeout(2000)
                .setSocketTimeout(5000)
                .build();

        httpClient = HttpClients.custom()
                .setDefaultRequestConfig(requestConfig)
                .setConnectionManager(cm)
                .setRetryHandler(retryHandler)
                .build();
    }

    public static void main(String[] args) {
        int threadCnt = 5;
        for (int i = 0; i < threadCnt; i++) {
            new Thread(() -> {
                for (int x = 0; x < 2; x++) {
                    try {
                        HttpUriRequest request = new HttpGet("http://localhost:8080/hello");
                        CloseableHttpResponse response = httpClient.execute(request);
                        HttpEntity entity = response.getEntity();
                        String result = EntityUtils.toString(entity, StandardCharsets.UTF_8);
                        System.err.println("The result is: " + result);
                        TimeUnit.MILLISECONDS.sleep(5);
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                }
            }, "cyh-test-20230120-" + i).start();
        }
    }


}
